// PizZip is required because docx/pptx/xlsx files are all zipped files, and
// the PizZip library allows us to load the file in memory
const PizZip = require("pizzip");
const Docxtemplater = require("docxtemplater");

const fs = require("fs");
const path = require("path");
const XLSX = require("xlsx");


function start(params) {
    if (process.argv.length <= 2) {
        console.log("请指定操作路径及数据文件");
        process.exit();
    }
    console.log(process.argv);
    var filePath = process.argv[2]
    var dataFile = process.argv[3]

    var stat = fs.lstatSync(filePath);
    var inputList = [];
    if (stat.isDirectory) {
        var childList = fs.readdirSync(filePath)
        childList.forEach(element => {
            if (fs.lstatSync(path.join(filePath, element)).isFile()) {
                inputList.push(path.join(filePath, element));
            }
        });
    } else {
        inputList.push(filePath)
    }

    console.log("inputList:", inputList);

    try {
        var cfg;
        switch (path.extname(dataFile)) {
            case ".json":
                const data = fs.readFileSync(
                    dataFile,
                    "utf8"
                );
                cfg = JSON.parse(data);
                break;
            case ".xlsx":
                var wb = XLSX.readFile(dataFile);
                cfg = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
                break;
            default:
                break;
        }
        console.log(cfg);
        for (let index = 0; index < inputList.length; index++) {
            const inputFile = inputList[index];
            renderMany(inputFile, cfg);
        }

    } catch (error) {
        console.log(error);
    }

}

function renderMany(inputFile, cfg, isMany = true) {
    // https://docxtemplater.com/docs/tag-types/
    // Load the docx file as binary content
    var fileInfo = path.parse(inputFile);
    if (!(fileInfo.ext == ".docx")) {
        return;
    }

    const content = fs.readFileSync(
        inputFile,
        "binary"
    );

    if (isMany && cfg instanceof Array) {
        for (let index = 0; index < cfg.length; index++) {
            const element = cfg[index];
            var outFile = "";
            //如果数据文件中约定了生成文件名则使用约定的名字，否是使用默认规则生成文件
            if (element.fileName){
                outFile = path.join(fileInfo.dir, "result", element.fileName + fileInfo.ext);
            }else{
                outFile = path.join(fileInfo.dir, "result", fileInfo.name + index + fileInfo.ext);
            }
            renderZip(content, element, outFile);
        }
    } else {
        renderZip(content, cfg, path.join(fileInfo.dir, "result", fileInfo.base));
    }
}

function renderZip(content, data, outFile) {
    console.log(data, outFile);
    // Unzip the content of the file
    const inputZip = new PizZip(content);
    const doc = new Docxtemplater(inputZip, {
        paragraphLoop: true,
        linebreaks: true,
    });
    doc.render(data);
    const buf = doc.getZip().generate({
        type: "nodebuffer",
        compression: "DEFLATE",
    });
    if (!fs.existsSync(path.dirname(outFile))) {
        fs.mkdirSync(path.dirname(outFile));
    }
    fs.writeFileSync(outFile, buf);
}


function test(params) {
    try {
        const data = fs.readFileSync(
            path.resolve(__dirname, "test", "data.json"),
            "utf8"
        );
        const cfg = JSON.parse(data);

        if (cfg instanceof Array) {

        } else {
            renderOne("input.docx", "output.docx", cfg);
        }

    } catch (error) {
        console.log(error);
    }
}

function renderOne(inputFile, outFile, data) {

    // https://docxtemplater.com/docs/tag-types/
    // Load the docx file as binary content
    const content = fs.readFileSync(
        path.resolve(__dirname, "test", inputFile),
        "binary"
    );

    // Unzip the content of the file
    const zip = new PizZip(content);

    // This will parse the template, and will throw an error if the template is
    // invalid, for example, if the template is "{user" (no closing tag)
    const doc = new Docxtemplater(zip, {
        paragraphLoop: true,
        linebreaks: true,
    });

    // Render the document (Replace {first_name} by John, {last_name} by Doe, ...)
    doc.render(data);

    // Get the zip document and generate it as a nodebuffer
    const buf = doc.getZip().generate({
        type: "nodebuffer",
        // compression: DEFLATE adds a compression step.
        // For a 50MB output document, expect 500ms additional CPU time
        compression: "DEFLATE",
    });

    // buf is a nodejs Buffer, you can either write it to a
    // file or res.send it with express for example.
    fs.writeFileSync(path.resolve(__dirname, "test", outFile), buf);
}

start();
